package myimage

import (
	"fmt"
	"image/png"
	"log"
	"os"
	"sort"

	"github.com/fogleman/gg"
)

var (
	font string = "font/Roboto-Bold.ttf"
)

func writeToFile(fileName string, content string) error {
	f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		// fmt.Println("file create failed. err: " + err.Error())
	} else {
		// offset
		//os.Truncate(filename, 0) //clear
		// fmt.Println(content)
		n, _ := f.Seek(0, os.SEEK_END)
		_, err = f.WriteAt([]byte(content), n)
		// fmt.Println("write succeed!")
		defer f.Close()
	}
	return err
}

func Test(bufname string) {
	// ttf("CH    SET    CUR    STATE", 20, "#ffffff", false, "input.png")
	// ttf("ON  ", 22, "#000000", "#ffffff", false, "input.png")
	ttf("     ON    ", 22, "#0000ff", "#ffffff", false, "input.png")

	// 打开原始的 PNG 图像文件
	inputFile, err := os.Open("input.png")
	if err != nil {
		log.Fatalf("failed to open input file: %v", err)
	}
	defer inputFile.Close()

	// 解码原始的 PNG 图像
	img, err := png.Decode(inputFile)
	if err != nil {
		log.Fatalf("failed to decode PNG: %v", err)
	}

	// 获取原始图像的尺寸
	bounds := img.Bounds()
	width, height := bounds.Dx(), bounds.Dy()

	bPicData := Rgb888_to_rgb565(img, true, 1)

	str := "const unsigned char " + bufname + "[] = {\r\n"
	str += fmt.Sprintf("/*width: %d, height: %d */", width, height)

	str += fmt.Sprintf("0x%x, 0x%x,\r\n", byte(width), byte(height))
	for i := 0; i < len(bPicData)-1; i++ {
		str += fmt.Sprintf("0x%02x,", bPicData[i])
		if (i+1)%15 == 0 {
			str += "\r\n"
		}
	}
	str += fmt.Sprintf("0x%02x", bPicData[len(bPicData)-1])
	str += "};"

	writeToFile("out.c", str)
}

func test_all(size int) {
	str := ""
	for i := 0; i < 94; i++ {
		str += string(byte(i + 32))
	}
	// str := "abcdefghijklmnopqrstuvwxyz"
	tempDC := gg.NewContext(1, 1) // 创建最小的上下文，仅用于测量
	tempDC.LoadFontFace(font, float64(size))
	sWidth, sHeight := tempDC.MeasureString(str)
	fmt.Println(sWidth, sHeight)

	dc := gg.NewContext(int(sWidth), int(size))
	dc.SetHexColor("#ff00ff") //白色背景

	dc.Clear() // 使用当前颜色（绿）填满画布，即设置背景色

	if err := dc.LoadFontFace(font, float64(size)); err != nil {
		panic(err)
	}

	dc.SetHexColor("#000000") // 设置画笔颜色为黑色

	// 绘制字符串，考虑到边距
	dc.DrawStringAnchored(str, float64(sWidth)/2, float64(sHeight)/2, 0.5, 0.5)
	// dc.DrawString(str, 0, sHeight)

	dc.SavePNG("test.png")
}

func ttf(str string, size int, color string, backcolor string, mode bool, filename string) ([]byte, int) {
	// 创建一个临时的绘图上下文来测量字符串
	tempDC := gg.NewContext(1, 1) // 创建最小的上下文，仅用于测量
	tempDC.LoadFontFace(font, float64(size))
	sWidth, sHeight := tempDC.MeasureString(str)
	fmt.Println(sWidth, sHeight)

	// 计算新的画布尺寸，包含边距
	newWidth := int(sWidth) + 1

	// 创建新的绘图上下文
	dc := gg.NewContext(newWidth, size)

	dc.SetHexColor(backcolor) //白色背景
	if mode {
		dc.SetRGBA(255, 255, 255, 255) //透明色
	}

	dc.Clear() // 使用当前颜色（绿）填满画布，即设置背景色

	if err := dc.LoadFontFace(font, float64(size)); err != nil {
		panic(err)
	}

	dc.SetHexColor(color) // 设置画笔颜色为黑色

	// 绘制字符串，考虑到边距
	// dc.DrawStringAnchored(str, float64(margin), float64(margin)+sHeight, 0, 0)
	dc.DrawString(str, 0, sHeight)

	img := dc.Image()

	// 获取原始图像的尺寸
	bounds := img.Bounds()
	width, _ := bounds.Dx(), bounds.Dy()

	b := Rgb888_to_rgb565(img, true, 1)

	dc.SavePNG(filename)

	return b, width
}

func num_gena(size int) {
	oneFlag := true
	cnt := 0

	s := "const unsigned char imageNum[] = {\r\n"
	for i := 0; i < 10; i++ {
		z := fmt.Sprintf("%d", i)
		b, w := ttf(z, size, "#000000", "#ffffff", false, "img/"+z+".png")

		if oneFlag {
			oneFlag = false
			s += fmt.Sprintf("/*font size:%d with:%d 0-9 */\r\n", size, w)
		}

		for i := 0; i < len(b); i++ {
			s += fmt.Sprintf("0x%02x,", b[i])
			cnt++
			if cnt%15 == 0 {
				s += "\r\n"
			}
		}
		// s += fmt.Sprintf("0x%02x", b[len(b)-1])
	}
	s += "};"
	writeToFile("img/num.c", s)
}

/**
 * @description: 生成全部ascii字符
 * @param {int} size
 * @param {string} color
 * @param {string} backcolor
 * @param {bool} mode
 * @return {*}
 */
func generate_letters(size int, color string, backcolor string, mode bool) {
	max := 0
	cnt := 0
	var height float64
	for i := 0; i < 94; i++ {
		tempDC := gg.NewContext(1, 1) // 创建最小的上下文，仅用于测量
		tempDC.LoadFontFace(font, float64(size))
		sWidth, sHeight := tempDC.MeasureString(string(byte(i)))
		// fmt.Println(sWidth, sHeight)
		if max < int(sWidth) {
			max = int(sWidth)
			height = float64(sHeight)
		}
	}

	fmt.Println(max, height)
	width := max

	str := fmt.Sprintf("const unsigned char ascii_%d[][%d] = {\r\n", size, width*size*2)
	fmt.Println(str)

	for i := 0; i < 94; i++ {
		s := string(byte(i + 32))

		dc := gg.NewContext(width, size)
		dc.SetHexColor(backcolor) //白色背景
		if mode {
			dc.SetRGBA(255, 255, 255, 255) //透明色
		}
		dc.Clear() // 使用当前颜色（绿）填满画布，即设置背景色

		if err := dc.LoadFontFace(font, float64(size)); err != nil {
			panic(err)
		}

		dc.SetHexColor(color) // 设置画笔颜色为黑色

		// 居中
		dc.DrawStringAnchored(s, float64(width)/2, float64(height)/2, 0.5, 0.5)
		// dc.DrawString(str, 0, height)

		img := dc.Image()

		// 获取原始图像的尺寸
		// bounds := img.Bounds()
		// fmt.Println(bounds.Dx(), bounds.Dy())

		b := Rgb888_to_rgb565(img, true, 1)

		str += fmt.Sprintf("\r\n{/*%s*/\r\n", s)
		cnt = 0
		for i := 0; i < len(b)-1; i++ {
			str += fmt.Sprintf("0x%02x,", b[i])
			cnt++
			if cnt%10 == 0 {
				str += "\r\n"
			}
		}
		str += fmt.Sprintf("0x%02x},", b[len(b)-1])

		dc.SavePNG("img/" + str + ".png")
	}
	str = str[:len(str)-1]
	str += "\r\n};"
	writeToFile("img/ascii_20.c", str)
}

// RemoveDuplicates 删除字符串中的重复字符，并按ASCII码排序
func RemoveDuplicates(s string) string {
	// 创建一个map来存储已出现的字符
	seen := make(map[rune]bool)
	// 创建一个切片来存储结果
	var result []rune

	// 遍历字符串中的每个字符
	for _, char := range s {
		// 如果字符没有出现在map中，则添加到结果切片中，并在map中标记为已出现
		if !seen[char] {
			seen[char] = true
			result = append(result, char)
		}
	}

	// 对结果切片进行排序
	sort.Slice(result, func(i, j int) bool {
		return result[i] < result[j]
	})

	// 将结果切片转换为字符串并返回
	return string(result)
}

func Set_ttf(ttffont string) {
	font = ttffont
}

func Generate_string(genStr string, size int, color string, backcolor string, mode bool, bufName string) string {
	cnt := 0
	length := 0
	genStr = RemoveDuplicates(genStr)
	// fmt.Println(genStr)
	// str := fmt.Sprintf("/*asciistr_%d记录字符的每个字符的宽度和对应字符在ascii%s_%d的位置\r\n", size, bufName, size)
	// str += "二维数组0位置记录字符宽度\r\n"
	// str += "二维数组1位置记录字符在字符数组中的起始位置\r\n"
	// str += "二维数组2位置记录字符*/\r\n"

	// str += fmt.Sprintf("#define ASCII%d_SIZE %d\r\n", size, size)
	str := fmt.Sprintf("const unsigned int asciitab_%d%s[][3] = {\r\n", size, bufName)

	for i := 0; i < len(genStr); i++ {
		s := genStr[i : i+1]
		tempDC := gg.NewContext(1, 1) // 创建最小的上下文，仅用于测量
		tempDC.LoadFontFace(font, float64(size))
		sWidth, _ := tempDC.MeasureString(s)
		// fmt.Println(s, sWidth, sHeight)
		str += fmt.Sprintf("{%d,%d,'%s'},\r\n", int(sWidth), length, s)
		length += int(sWidth) * size * 2
	}
	str = str[:len(str)-1]
	str += "};\r\n"

	str += fmt.Sprintf("const unsigned char ascii_%d%s[] = {\r\n /*%s*/", size, bufName, genStr)

	for i := 0; i < len(genStr); i++ {
		s := genStr[i : i+1]

		tempDC := gg.NewContext(1, 1) // 创建最小的上下文，仅用于测量
		tempDC.LoadFontFace(font, float64(size))
		sWidth, sHeight := tempDC.MeasureString(s)

		dc := gg.NewContext(int(sWidth), size)
		dc.SetHexColor(backcolor) //白色背景
		if mode {
			dc.SetRGBA(255, 255, 255, 255) //透明色
		}
		dc.Clear() // 使用当前颜色（绿）填满画布，即设置背景色

		if err := dc.LoadFontFace(font, float64(size)); err != nil {
			panic(err)
		}

		dc.SetHexColor(color) // 设置画笔颜色为黑色

		// 居中
		dc.DrawStringAnchored(s, float64(sWidth)/2, float64(sHeight)/2, 0.5, 0.5)

		img := dc.Image()

		b := Rgb888_to_rgb565(img, true, 1)

		str += fmt.Sprintf("\r\n/*%s*/\r\n", s)
		cnt = 0
		for j := 0; j < len(b); j++ {
			str += fmt.Sprintf("0x%02x,", b[j])
			cnt++
			if cnt%10 == 0 {
				str += "\r\n"
			}
		}
		// dc.SavePNG("img/" + s + ".png")
	}
	if str[len(str)-1] == ',' {
		str = str[:len(str)-1]
	} else {
		str = str[:len(str)-3]
	}

	str += "\r\n};"
	// writeToFile("img/ascii"+strconv.Itoa(size)+".c", str)

	return str
}
